#ifndef __INCLUDED_CBL_INTRUSIVE_LIST_H__
#error "CBL_IntrusiveList.hpp must not be used directly. Use CBL_IntrusiveList.h instead."
#else
#ifndef __INCLUDED_CBL_INTRUSIVE_LIST_HPP__
#define __INCLUDED_CBL_INTRUSIVE_LIST_HPP__

#define INTRUSIVELIST_TYPE CIntrusiveList<TItemClass, TListId>

template <typename TItemClass, uint32 TListId>
INTRUSIVELIST_TYPE::CIntrusiveList()
: m_pFirst(NULL)
, m_pLast(NULL)
, m_Size(0)
{
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
INTRUSIVELIST_TYPE::~CIntrusiveList()
{
	Clear();
}

// -------------------------------------------------------------------------------------


template <typename TItemClass, uint32 TListId>
void INTRUSIVELIST_TYPE::PushBack(typename INTRUSIVELIST_TYPE::CItem& _rItem)
{
	Remove(_rItem);
	
	_rItem.m_pIntrusiveListPrev = m_pLast;
	
	if (m_pLast)
		m_pLast->m_pIntrusiveListNext = &_rItem;
	else
		m_pFirst = &_rItem;
	
	m_pLast = &_rItem;
	
	_rItem.m_pIntrusiveListParent = this;
	++m_Size;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
void INTRUSIVELIST_TYPE::PushFront(typename INTRUSIVELIST_TYPE::CItem& _rItem)
{
	Remove(_rItem);
	
	_rItem.m_pIntrusiveListNext = m_pFirst;
	
	if (m_pFirst)
		m_pFirst->m_pIntrusiveListPrev = &_rItem;
	else
		m_pLast = &_rItem;
	
	m_pFirst = &_rItem;
	
	_rItem.m_pIntrusiveListParent = this;
	++m_Size;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
void INTRUSIVELIST_TYPE::Insert(typename INTRUSIVELIST_TYPE::CItem& _rItem, typename INTRUSIVELIST_TYPE::CItem& _rNewNext)
{
	if (&_rItem == &_rNewNext) return;
	
	Remove(_rItem);
	
	_rItem.m_pIntrusiveListPrev = _rNewNext.m_pIntrusiveListPrev;
	_rItem.m_pIntrusiveListNext = &_rNewNext;
	
	if (_rItem.m_pIntrusiveListPrev)
		_rItem.m_pIntrusiveListPrev->m_pIntrusiveListNext = &_rItem;
	else
		m_pFirst = &_rItem;
	
	_rNewNext.m_pIntrusiveListPrev = &_rItem;
	_rItem.m_pIntrusiveListParent = this;
	++m_Size;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
void INTRUSIVELIST_TYPE::Remove(typename INTRUSIVELIST_TYPE::CItem& _rItem)
{
	if (_rItem.m_pIntrusiveListNext != NULL)
	{
		_rItem.m_pIntrusiveListNext->m_pIntrusiveListPrev = _rItem.m_pIntrusiveListPrev;
	}
	else if (_rItem.m_pIntrusiveListParent != NULL)
	{
		_rItem.m_pIntrusiveListParent->m_pLast = _rItem.m_pIntrusiveListPrev;
	}
	
	if (_rItem.m_pIntrusiveListPrev != NULL)
	{
		_rItem.m_pIntrusiveListPrev->m_pIntrusiveListNext = _rItem.m_pIntrusiveListNext;
	}
	else if (_rItem.m_pIntrusiveListParent != NULL)
	{
		_rItem.m_pIntrusiveListParent->m_pFirst = _rItem.m_pIntrusiveListNext;
	}
	
	if (_rItem.m_pIntrusiveListParent)
	{
		--_rItem.m_pIntrusiveListParent->m_Size;
	}
	
	_rItem.m_pIntrusiveListPrev = NULL;
	_rItem.m_pIntrusiveListNext = NULL;
	_rItem.m_pIntrusiveListParent = NULL;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CItem* INTRUSIVELIST_TYPE::PopFront()
{
	CItem* pOldFirst = m_pFirst;
	
	if (m_pFirst)
	{
		m_pFirst = m_pFirst->m_pIntrusiveListNext;
		
		if (m_pFirst)
			m_pFirst->m_pIntrusiveListPrev = NULL;
		else
			m_pLast = NULL;
	}
	
	pOldFirst->m_pIntrusiveListNext = NULL;
	pOldFirst->m_pIntrusiveListPrev = NULL;
	
	return pOldFirst;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CItem* INTRUSIVELIST_TYPE::PopBack()
{
	CItem* pOldLast = m_pLast;
	
	if (m_pLast)
	{
		m_pLast = m_pLast->m_pIntrusiveListPrev;
		
		if (m_pLast)
			m_pLast->m_pIntrusiveListNext = NULL;
		else
			m_pFirst = NULL;
	}
	
	pOldLast->m_pIntrusiveListNext = NULL;
	pOldLast->m_pIntrusiveListPrev = NULL;
	
	return pOldLast;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
void INTRUSIVELIST_TYPE::Clear()
{
	CItem* pIter = m_pFirst;
	
	while (pIter)
	{
		pIter->m_pIntrusiveListParent = NULL;
		pIter = pIter->m_pIntrusiveListNext;
	}
	
	m_Size = 0;
	m_pFirst = NULL;
	m_pLast = NULL;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
bool INTRUSIVELIST_TYPE::IsEmpty()
{
	return ((m_pFirst == NULL) && (m_pLast == NULL));
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
uint32 INTRUSIVELIST_TYPE::Size()
{
	return m_Size;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CIterator INTRUSIVELIST_TYPE::Begin()
{
	return CIterator(m_pFirst);
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CIterator INTRUSIVELIST_TYPE::End()
{
	return CIterator(NULL);
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CIterator INTRUSIVELIST_TYPE::RBegin()
{
	return CIterator(m_pLast);
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CIterator& INTRUSIVELIST_TYPE::CIterator::operator += (int _Count)
{
	for (int i(0); (i<_Count) && IsValid(); ++i, ++(*this));
	return *this;
}

// -------------------------------------------------------------------------------------

template <typename TItemClass, uint32 TListId>
typename INTRUSIVELIST_TYPE::CIterator INTRUSIVELIST_TYPE::CIterator::operator + (int _Count)
{
	CIterator NewIter(m_pCurrent);
	for (int i(0); (i<_Count) && NewIter.IsValid(); ++i, ++NewIter);
	return NewIter;
}

#undef INTRUSIVELIST_TYPE

#endif
#endif